package xyz.app.dependencies;

import lombok.NonNull;
import xyz.app.Wrapper;
import xyz.app.accessors.DbAccessor;
import xyz.app.AbstractDomain;

import java.util.Collection;

public interface HasOwners<T extends AbstractDomain> extends DbAccessor<T> {

    Collection<OwnerEntry<?, T>> ownersMapping();

    private boolean hasIrremovableOwners(@NonNull AbstractDomain domain) {

        var hasIrremovableOwners = ownersMapping().stream()
                .filter(oe -> !oe.isRemovableFrom(domainClass()))
                .anyMatch(om -> !om.getDao().find(om.getName(), domain).isEmpty());

        info(hasIrremovableOwners
                ? "Entity [{}] has irremovable owners and thus cannot be removed from database"
                : "Entity [{}] does not have irremovable owners and thus can be removed from database", domain.string());

        return hasIrremovableOwners;
    }

    default boolean removeOwners(@NonNull AbstractDomain domain) {
        return !hasIrremovableOwners(domain);
    }

    interface IsRemovableOrphan<T extends AbstractDomain> extends HasOwners<T> {

    }

    interface HasRemovableOwners<T extends AbstractDomain> extends HasOwners<T> {

        @Override
        default boolean removeOwners(@NonNull AbstractDomain domain) {

            if (HasOwners.super.hasIrremovableOwners(domain)) return false;

            return ownersMapping().stream()
                    .filter(oe -> oe.isRemovableFrom(domainClass()))
                    .map(om -> om.getDao().find(om.getName(), domain))
                    .flatMap(Collection::stream)
                    .peek(removeOwner -> info("Removable owner found: [{}]", removeOwner.string()))
                    .allMatch(removableOwner -> getDao(removableOwner.domainClass())
                            .map(dao -> dao.delete(Wrapper.wrap(removableOwner)))
                            .orElse(false));
        }
    }
}